package com.weakteam.orderonline.administratorconsole.gwt.client.design;


import com.allen_sauer.gwt.dnd.client.PickupDragController;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.http.client.*;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.*;
import com.weakteam.orderonline.administratorconsole.gwt.client.domain.Menu;
import com.weakteam.orderonline.administratorconsole.gwt.client.util.ConsoleLog;
import com.weakteam.orderonline.administratorconsole.gwt.client.util.uploader.drop.DropHandler;
import com.weakteam.orderonline.administratorconsole.gwt.client.util.uploader.file.*;
import com.weakteam.orderonline.administratorconsole.gwt.client.widget.OrderMenuDraggableBox;
import com.weakteam.orderonline.administratorconsole.gwt.client.widget.OrderMenuDraggableBoxDropController;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;



/**
 *
 * @author Nail
 */
public class MenuEditPage extends Composite {

    private static MenuEditUiBinder uiBinder = GWT.create(MenuEditUiBinder.class);

    interface MenuEditUiBinder extends UiBinder<Widget, MenuEditPage> {
    }
    private static MenuEditPage instance = null;

    public static MenuEditPage getInstance() {
        if (instance == null) {
            instance = new MenuEditPage();
        }
        return instance;
    }

    public MenuEditPage() {
        initWidget(uiBinder.createAndBindUi(this));
        this.initPage();
    }

    @UiField
    protected AbsolutePanel orderPanel;
    @UiField
    protected VerticalPanel verticalMenuPanel;
    @UiField
    protected Button addOrderButton;
    @UiField
    protected Button saveButton;
    @UiField
    protected Button mDelete;

    // form fields
    @UiField
    protected Label mLabelEnabled;
    @UiField
    protected Button mEnabled;
    @UiField
    protected TextBox mName;
    @UiField
    protected TextArea mDescription;
    @UiField
    protected Image mIco;
    @UiField
    protected Image mImage;
    @UiField
    protected TextArea mProperties;

    private PickupDragController widgetDragController;
    private List<OrderMenuDraggableBox> orderMenuDraggableBox;

    private void initPage() {

        // init goods menu
        {
            // initialize our widget drag controller
            this.widgetDragController = new PickupDragController(orderPanel, false);
            this.widgetDragController.setBehaviorMultipleSelection(false);

            // initialize a widget drop controller for the current column
            OrderMenuDraggableBoxDropController widgetDropController = new OrderMenuDraggableBoxDropController(verticalMenuPanel);
            this.widgetDragController.registerDropController(widgetDropController);

            this.loadData();
        }

        addOrderButton.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                Menu menu = new Menu();
                MenuEditPage.this.saveData(menu);
            }
        });

        saveButton.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                for (Iterator<OrderMenuDraggableBox> it = orderMenuDraggableBox.iterator(); it.hasNext(); ) {
                    OrderMenuDraggableBox box = it.next();
                    box.getMenu().setOrder(verticalMenuPanel.getWidgetIndex(box));
                    if (box.isActive()) MenuEditPage.this.save(box); // save current open box
                    MenuEditPage.this.saveData();
                }
            }
        });

        mEnabled.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                boolean isEnabled = mLabelEnabled.getText().compareTo("Активно") == 0;
                if (isEnabled) {
                    mLabelEnabled.setText("Не активно");
                    mEnabled.setText("Активировать");
                } else {
                    mLabelEnabled.setText("Активно");
                    mEnabled.setText("Деактивировать");
                }
                OrderMenuDraggableBox currentBox = MenuEditPage.this.getCurrentBox();
                currentBox.setEnabled(!isEnabled);
            }
        });

        mDelete.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                int currentId = MenuEditPage.this.getCurrentBox().getMenu().getId();
                MenuEditPage.this.deleteData(currentId);
            }
        });

        DropHandler imageDropHandler = new DropHandler(mImage);
        imageDropHandler.addFileEventHandler(new FileEvent.FileEventHandler() {
            @Override
            public void onFiles(FileEvent event) {
                JsArray<File> files = event.getFiles();
                File file = MenuEditPage.this.checkImageFiles(files);
                MenuEditPage.this.uploadImageFile(file, FileUtil.IMAGE);
            }
        });

        DropHandler icoDropHandler = new DropHandler(mIco);
        icoDropHandler.addFileEventHandler(new FileEvent.FileEventHandler() {
            @Override
            public void onFiles(FileEvent event) {
                JsArray<File> files = event.getFiles();
                File file = MenuEditPage.this.checkImageFiles(files);
                MenuEditPage.this.uploadImageFile(file, FileUtil.ICO);
            }
        });
    }

    private OrderMenuDraggableBox getCurrentBox() {
        for (Iterator<OrderMenuDraggableBox> it = orderMenuDraggableBox.iterator(); it.hasNext();) {
            OrderMenuDraggableBox box = it.next();
            if (box.isActive()) return box;
        }
        return null;
    }


    private void addOrderDraggableBox(final Menu menu) {
        final OrderMenuDraggableBox box = new OrderMenuDraggableBox();
        box.init(menu, this.orderMenuDraggableBox);
        box.setEnabled(menu.getEnabled());
        this.verticalMenuPanel.add(box);

        this.orderMenuDraggableBox.add(box);

        // make the widget draggable
        widgetDragController.makeDraggable(box);
    }

    public void setActive(OrderMenuDraggableBox box) {
        Menu menu = box.getMenu();
        if (menu.getEnabled()) {
            mLabelEnabled.setText("Активно");
            mEnabled.setText("Деактивировать");
        } else {
            mLabelEnabled.setText("Не активно");
            mEnabled.setText("Активировать");
        }
        mName.setText(menu.getName());
        mDescription.setText(menu.getDescription());
        mImage.setUrl(FileUtil.getImageURL(menu.getImage()));
        mIco.setUrl(FileUtil.getImageURL(menu.getIco()));
        mProperties.setText(menu.getProperties());
    }

    public void save(OrderMenuDraggableBox box) {
        Menu menu = box.getMenu();
        menu.setEnabled(mLabelEnabled.getText().compareTo("Активно") == 0);
        menu.setName(mName.getText());
        menu.setDescription(mDescription.getText());
        menu.setProperties(mProperties.getText());
    }

    public File checkImageFiles(JsArray<File> files) {
        if (files.length() > 1) {
            Window.alert("Можно добавить только один файл");
        }
        File file = files.get(0);
        String fName = file.getFileName();
        int fSize = file.getFileSize();
        ConsoleLog.getInstance().debug("file name: " + fName);
        ConsoleLog.getInstance().debug("file size: " + fSize);
        if (fSize > 300 * 1024) {
            Window.alert("Файл " + fName + " слишком большой (размер файла не должен превышать 100kb)");
            return null;
        } else if (!fName.endsWith(".png") && !fName.endsWith(".jpg")) {
            Window.alert("Файл " + fName + " не является файлом png или jpg");
            return null;
        } else {
            return file;
        }
    }

    public void uploadImageFile(final File file, final int fileNature) {
        String fileName = file.getFileName();
        String url = GWT.getHostPageBaseURL() + "/uploadImage?name=" + fileName;

        FileUploader fileUploader = new FileUploader();
        fileUploader.addUploadHandler(new UploadHandler() {
            @Override
            public void onUploadProgress(Float percentage) {
                ConsoleLog.getInstance().debug("completed: " + percentage);
            }

            @Override
            public void onUploadCompleted(String savedFileName) {
                ConsoleLog.getInstance().debug("uploaded completed new fileName:" + savedFileName);
                if (fileNature == FileUtil.IMAGE) {
                    MenuEditPage.this.mImage.setUrl(FileUtil.getImageURL(savedFileName));
                    MenuEditPage.this.getCurrentBox().getMenu().setImage(savedFileName);
                } else if (fileNature == FileUtil.ICO) {
                    MenuEditPage.this.mIco.setUrl(FileUtil.getImageURL(savedFileName));
                    MenuEditPage.this.getCurrentBox().getMenu().setIco(savedFileName);
                }
            }
            @Override
            public void onUploadError() {
                ConsoleLog.getInstance().debug("upload error");
            }
        });
        fileUploader.upload(file, url);
    }





    // http request

    // loadData request
    private void loadData() {
        RequestBuilder builder = new RequestBuilder(RequestBuilder.GET,
                GWT.getHostPageBaseURL() + "/getMenuData");
        try {
            builder.sendRequest(null, new RequestCallback() {

                @Override
                public void onError(Request request, Throwable exception) {
                    ConsoleLog.getInstance().error("loadData onError: " + exception);
                }
                @Override
                public void onResponseReceived(Request request, Response response) {
                    if (200 == response.getStatusCode()) {
                        MenuEditPage.this.loadDataResponse(response.getText());
                    }
                }
            });
        } catch (RequestException exception) {
            ConsoleLog.getInstance().error("loadData catch error: " + exception);
        }
    }

    // loadData response
    private void loadDataResponse(String json) {
        ConsoleLog.getInstance().debug("loadDataResponse " + json);
        JSONArray data = (JSONArray) JSONParser.parseLenient(json);
        int n = data.size();
        this.verticalMenuPanel.clear();
        this.orderMenuDraggableBox = new ArrayList<OrderMenuDraggableBox>(n);

        if (n > 0) {
            for(int i = 0; i < n; i++) {
                JSONObject obj = data.get(i).isObject();
                final Menu menu = new Menu();
                menu.set(obj);
                this.addOrderDraggableBox(menu);
            }
            this.orderMenuDraggableBox.get(0).setActive();
        }
    }


    // saveData
    private void saveData(Menu menu) {
        RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, GWT.getHostPageBaseURL() + "/saveMenuDataOne");
        builder.setHeader("Content-type", "application/x-www-form-urlencoded");
        StringBuffer postData = new StringBuffer();
        postData.append(URL.encode("menu")).append("=").append(URL.encode(menu.getJSON().toString()));
        try {
            builder.sendRequest(postData.toString(), new RequestCallback() {

                @Override
                public void onError(Request request, Throwable exception) {
                    ConsoleLog.getInstance().error("saveData onError: " + exception);
                }
                @Override
                public void onResponseReceived(Request request, Response response) {
                    if (200 == response.getStatusCode()) {
                        MenuEditPage.this.loadData();
                    }
                }
            });
        } catch (RequestException exception) {
            ConsoleLog.getInstance().error("saveData catch error: " + exception);
        }
    }

    // saveData
    private void saveData() {
        if (this.orderMenuDraggableBox != null && this.orderMenuDraggableBox.size() > 0) {
            RequestBuilder builder = new RequestBuilder(RequestBuilder.POST,
                    GWT.getHostPageBaseURL() + "/saveMenuData");
            builder.setHeader("Content-type", "application/x-www-form-urlencoded");

            JSONArray data = new JSONArray();
            int i = 0;
            for (Iterator<OrderMenuDraggableBox> it = orderMenuDraggableBox.iterator(); it.hasNext(); ) {
                Menu menu = it.next().getMenu();
                data.set(i++, menu.getJSON());
            }

            StringBuffer postData = new StringBuffer().append(URL.encode("data")).append("=").append(URL.encode(data.toString()));
            try {
                Request request = builder.sendRequest(postData.toString(), new RequestCallback() {

                    @Override
                    public void onError(Request request, Throwable exception) {
                        ConsoleLog.getInstance().error("saveData onError: " + exception);
                    }

                    @Override
                    public void onResponseReceived(Request request, Response response) {
                        if (200 == response.getStatusCode()) {
                            MenuEditPage.this.loadData();
                        }
                    }
                });
            } catch (RequestException exception) {
                ConsoleLog.getInstance().error("saveData catch error: " + exception);
            }
        }
    }

    // deleteData
    private void deleteData(Integer id) {
        RequestBuilder builder = new RequestBuilder(RequestBuilder.POST,
                GWT.getHostPageBaseURL() + "/deleteMenuData");
        builder.setHeader("Content-type", "application/x-www-form-urlencoded");
        StringBuffer postData = new StringBuffer();
        postData.append(URL.encode("id")).append("=").append(URL.encode(id.toString()));
        try {
            builder.sendRequest(postData.toString(), new RequestCallback() {

                @Override
                public void onError(Request request, Throwable exception) {
                    ConsoleLog.getInstance().error("deleteData onError: " + exception);
                }
                @Override
                public void onResponseReceived(Request request, Response response) {
                    if (200 == response.getStatusCode()) {
                        MenuEditPage.this.loadData();
                    }
                }
            });
        } catch (RequestException exception) {
            ConsoleLog.getInstance().error("deleteData catch error: " + exception);
        }
    }
}